Small overview of HoloViz capability of data exploration¶
This notebook is intended to present a small overview of HoloViz and the capability for data exploration, with interactive plots (show difference between matplotlib and bokeh). Many parts are based on or copied from the official HoloViz Tutorial (highly recommended for a more extensive overview of the possibilities of HoloViz).
Note: In June 2019 the project name changed from PyViz to HoloViz. The reason for this is explained in this blog post.
Exploring Pandas Dataframes¶
If your data is in a Pandas dataframe, it’s natural to explore it using the .plot() method (based on Matplotlib). Let’s have a look at some automatic weather station data from Langenferner:
import pandas as pd
url = 'https://cluster.klima.uni-bremen.de/~oggm/tutorials/aws_data_Langenferner_UTC+2.csv'
df = pd.read_csv(url, index_col=0, parse_dates=True)
df.head()
| TEMP | RH | SWIN | SWOUT | LWIN | LWOUT | WINDSPEED | WINDDIR | PRESSURE | |
|---|---|---|---|---|---|---|---|---|---|
| 2013-07-13 00:00:00 | 1.634333 | 67.595753 | 0.0 | 0.0 | 212.744817 | 303.656833 | 4.436833 | 211.533333 | 692.622250 |
| 2013-07-13 01:00:00 | 1.388667 | 68.150512 | 0.0 | 0.0 | 209.781683 | 302.588717 | 5.544000 | 206.166667 | 692.395683 |
| 2013-07-13 02:00:00 | 1.064500 | 66.853977 | 0.0 | 0.0 | 207.234933 | 300.872133 | 5.573167 | 210.750000 | 692.200800 |
| 2013-07-13 03:00:00 | 0.985167 | 55.827547 | 0.0 | 0.0 | 207.913533 | 295.684267 | 3.970167 | 203.250000 | 692.163967 |
| 2013-07-13 04:00:00 | 1.155333 | 43.371014 | 0.0 | 0.0 | 211.513517 | 292.688400 | 3.267000 | 203.366667 | 692.001667 |
Just calling .plot() won’t give anything meaningful, because of the different magnitudes of the parameters:
df.plot();
Of course we can have a look at one variable only:
df.TEMP.plot();
This creates a static plot using matplotlib. With this approach we also can make some further explorations, like calculating the monthly mean temperature:
dfm = df.resample('m').mean()
dfm.TEMP.plot();
We can see the course of the parameter but we can not tell what was the exact temperature at January and we also cannot zoom in.
Exploring Data with hvPlot and Bokeh¶
If we are using hvplot instead we can create interactive plots with the same plotting API:
you might need to install first hvplot via e.g. conda install -c pyviz hvplot
import hvplot.pandas
df.TEMP.hvplot()
Now you have an interactive plot using bokeh with zooming option and hover with additional information (get the exact values and timestamps), also possible for all variables but again not very meaningful:
plot = df.hvplot()
plot
But at least you can use your mouse to hover over each variable and explore their values. Furthermore, by clicking on the legend the colors can be switched on/off. Still, different magnitudes make it hard to see all parameters at once.
Here the interactive features are provided by the Bokeh JavaScript-based plotting library. But what’s actually returned by this call is a overlay of something called a HoloViews object, here specifically a HoloViews Curve. HoloViews objects display as a Bokeh plot, but they are actually much richer objects that make it easy to capture your understanding as you explore the data.
print(plot)
:NdOverlay [Variable]
:Curve [index] (value)
This object can be converted to a HoloMap object (using the HoloViews Package and declare bokeh to use for plotting) to create a widget that can be used to select the variables from.
import holoviews as hv
hv.extension('bokeh')
holo_plot = hv.HoloMap(plot)
print(holo_plot)
:HoloMap [Variable]
:Curve [index] (value)
holo_plot.opts(width=700, height=500)
But first have a look at the HoloViews Objects.
HoloViews Objects¶
Creating a simple HoloViews Object:
import numpy as np
xs = np.arange(-10, 10.5, 0.5)
ys = 100 - xs**2
df_xy = pd.DataFrame(dict(x=xs, y=ys))
simple_curve = hv.Curve(df_xy, 'x', 'y')
print(simple_curve)
:Curve [x] (y)
:Curve [x] (y) is HoloViews’s shorthand for saying that the data in df_xy is a set of samples from a continuous function y of one independent variable x, and simple_curve simply pairs your dataframe df_xy with this semantic declaration.
Once we’ve captured this crucial bit of metadata, HoloViews now knows enough about this object to represent it graphically, as it will do by default in a Jupyter notebook:
simple_curve
This Bokeh plot is much more convenient to examine than a column of numbers, because it conveys the entire set of data in a compact, easily appreciated, interactively explorable format. HoloViews knew that a continuous curve like this is the right representation for what would otherwise be just a table of numbers, because we explicitly declared the element type as hv.Curve. Crucially, simple_curve itself is not a plot, it’s just a simple wrapper around your data that happens to have a convenient graphical representation. The full dataframe will always be available as simple_curve.data, for any numerical computations you would like to do:
simple_curve.data.tail()
| x | y | |
|---|---|---|
| 36 | 8.0 | 36.00 |
| 37 | 8.5 | 27.75 |
| 38 | 9.0 | 19.00 |
| 39 | 9.5 | 9.75 |
| 40 | 10.0 | 0.00 |
As you can see, with HoloViews you don’t have to select between plotting your data and working with it numerically. Any HoloViews object will let you do both conveniently; you can simply choose whatever representation is the most appropriate way to approach the task you are doing. This approach is very different from a traditional plotting program, where the objects you create (e.g. a Matplotlib figure or a native Bokeh plot) are a dead end from an analysis perspective, useful only for plotting.
HoloViews Elements¶
Holoview objects merge the visualization with the data. For an Holoview object you have to classify what the data is showing. A Holoview object could be initialised in several ways:
hv.Element(data, kdims=None, vdims=None, **kwargs)
This standard signature consists of the same five types of information:
Element: any of the dozens of element types shown in the reference gallery.data: your data in one of a number of formats described below, such as tabular dataframes or multidimensional gridded Xarray or Numpy arrays.kdims: “key dimension(s)”, also called independent variables or index dimensions in other contexts—the values for which your data was measured.vdims: “value dimension(s)”, also called dependent variables or measurements—what was measured or recorded for each value of the key dimensions.kwargs: optional keyword arguments specific to thatElementtype (rarely needed).
Elements could be for example Curve, Scatter, Area and also different ways of declaring the key dimension(s) and value dimension(s) are shown below:
(hv.Curve(df_xy, kdims=('x','x_label'), vdims=('y','y_label')) +
hv.Scatter((xs,ys)).redim.label(x='x_label', y='ylabel') +
hv.Area({'x':xs,'y':ys}))
The example also shows two ways of labeling the variables, one is directly by the initialisation with tuples ('x','x_label') and ('y','y_label') and a other option is to use .redim.label().
The example above also shows the simple syntax to create a layout of different Holoview Objects by using +. With * you can simply overlay the objects in one plot:
from holoviews import opts
(hv.Curve(df_xy, 'x', 'y') *
hv.VLine(5).opts(color='black') *
hv.HLine(75).opts(color='red'))
With .opts() you can change some characteristics of the Holoview Objects and you can use the [tab] key completion to see, what options are available or you can use the hv.help() function to get more information about some Elements.
# hv.help(hv.Curve)
So now we can use some Holoview object for the data exploration for the glacier data. We create a Layout with some subplots for the different parameters. With opts.defaults() we can change some default properties of the different HoloView Elements, here we activate the hover tool for all Curve elements. Try to zoom into one plot!
opts.defaults(opts.Curve(tools=['hover']))
(hv.Curve(df, 'index', 'TEMP') +
hv.Curve(df,'index','RH') +
hv.Curve(df,'index','SWIN').opts(color='darkorange') * hv.Curve(df,'index','SWOUT').opts(color='red') +
hv.Curve(df,'index','LWIN').opts(color='darkorange') * hv.Curve(df,'index','LWOUT').opts(color='red') +
hv.Curve(df,'index','WINDSPEED') +
hv.Curve(df,'index','WINDDIR')).cols(3).opts(opts.Curve(width=300, height=200))
So here we created a Curve Element for some Parameters and put them together in subplots by using + and overlay some in one subplot with *. With .opts() I define the color of some parameters and set the width and height propertie for the used Curve Elements and with .cols() I define the number of columns.
Now we can zoom in and use a hover for data exploration and because all Holoview Objects using the same dataframe and the same key variable the x-axes of all plots are linked. So when you zoom in in one plot all the other plots are zoomed in as well.
HoloView Dataset and HoloMap Objects¶
A HoloViews Dataset is similar to a HoloViews Element, without having any specific metadata that lets it visualize itself. A Dataset is useful for specifying a set of Dimensions that apply to the data, which will later be inherited by any visualizable elements that you create from the Dataset.
A HoloViews Dimension is the same concept as a dependent or independent variable in mathematics. In HoloViews such variables are called value dimensions and key dimensions (respectively). So lets take again our glacier pandas DataFrame and create a HoloView Dataset. Beforehand we define some new columns for the date. Then we create our HoloView DataFrame with the key variables (independent) month, year and day_hour. The remaining columns will automatically be inferred to be value (dependent) dimensions:
df['month'] = df.index.month
df['year'] = df.index.year
df['day_hour'] = df.index.day + df.index.hour/24
df['timestamp'] = df.index.strftime('%d.%m.%Y %H:%M')
df_month = hv.Dataset(df, ['month', 'year', 'day_hour'])
df_month = df_month.redim.label(day_hour='day of month')
df_month
:Dataset [month,year,day_hour] (TEMP,RH,SWIN,SWOUT,LWIN,LWOUT,WINDSPEED,WINDDIR,PRESSURE,timestamp)
Out of this Dataset we now can create a Holomap with .to. The .to method of a Dataset takes up to four main arguments:
The element you want to convert to
The key dimensions (i.e., independent variables) to display
The dependent variables to display, if any
The dimensions to group by, if nothing given the remaining key variables are used
slider = df_month.to(hv.Curve, ['day_hour'], ['TEMP', 'RH', 'SWIN', 'timestamp'])
slider = slider.opts(width=600, height=400, tools=['hover'])
print(slider)
:HoloMap [month,year]
:Curve [day_hour] (TEMP,RH,SWIN,timestamp)
We now created a HoloMap with to grouped variables [month, year], one key variable [day_hour] and five dependent variables (TEMP, RH, SWIN, WINDSPEED, timestamp). Now look at the visualisation (some months/year pairs are missing and cannot be visualized):
slider
We see that a widget was created where we can choose the 'month' and the 'year' (the two grouped variables). The plot is showing the 'day_hour' (key) variable against the first dependent variable 'TEMP'. The other dependent variables are not shown but their values are displayed in the hover.
For a better comparison we also can look at grouped variables at once when we use .overlay():
overlay = df_month.to(hv.Curve, ['day_hour'], ['TEMP', 'RH', 'SWIN','WINDSPEED','timestamp']).overlay()
overlay = overlay.opts(width=800, height=500, tools=['hover'])
overlay.opts(opts.NdOverlay(legend_muted=True, legend_position='left'))
print(overlay)
:NdOverlay [month,year]
:Curve [day_hour] (TEMP,RH,SWIN,WINDSPEED,timestamp)
Here we are creating an NdOverlay Object which is similar to a HoloMap, but has a different visualisation:
overlay
Here now no widget is created, instead there is a interactive legend where we can turn the color on by clicking in the legend on it. So we can compare the months with each other (for example the same month in different years).
It is also easy to look at some mean values, for example looking at mean diurnal values for each month and year you can use .aggregate, which combine the values after the given function:
df['hour'] = df.index.hour
df_mean = hv.Dataset(df, ['month', 'year', 'hour']).aggregate(function=np.mean)
df_mean = df_mean.redim.label(hour='hour of the day')
print(df_mean)
:Dataset [month,year,hour] (TEMP,RH,SWIN,SWOUT,LWIN,LWOUT,WINDSPEED,WINDDIR,PRESSURE,day_hour)
.aggregate() uses the key variables and looks where all of them are the same. It uses the provided function (in the case above np.mean) to calculate new values. So in the above case we calculate mean daily cycles for each month and year. The calculated Dataset then can be displayed as we have seen it above.
slider = df_mean.to(hv.Curve, ['hour'], ['TEMP', 'RH', 'SWIN']).opts(width=600, height=400, tools=['hover'])
print(slider)
slider
:HoloMap [month,year]
:Curve [hour] (TEMP,RH,SWIN)
overlay = df_mean.to(hv.Curve, ['hour'], ['TEMP', 'RH', 'SWIN']).opts(width=600, height=400, tools=['hover']).overlay()
overlay.opts( opts.NdOverlay(legend_muted=True, legend_position='left'))
print(overlay)
overlay
:NdOverlay [month,year]
:Curve [hour] (TEMP,RH,SWIN)
Using GeoView for displaying geographical data¶
As a small example for using geoview I want to show how to display a shapefiles of glaciers in an interactive plot.
import geoviews as gv
import geopandas as gpd
you might have to install geoviews for that!
Tile sources¶
Tile sources are very convenient ways to provide geographic context for a plot and they will be familiar from the popular mapping services like Google Maps and Openstreetmap. The WMTS element provides an easy way to include such a tile source in your visualization simply by passing it a valid URL template. GeoViews provides a number of useful tile sources in the gv.tile_sources module:
import geoviews.tile_sources as gts
layout = gv.Layout([ts.relabel(name) for name, ts in gts.tile_sources.items()])
layout.opts('WMTS', xaxis=None, yaxis=None, width=225, height=225).cols(4)
To read the shape file geopandas could be used:
from oggm import utils
europe_glacier = gpd.read_file(utils.get_rgi_region_file('11', version='61'))
hintereisferner = europe_glacier[europe_glacier.Name == 'Hintereisferner'].geometry.iloc[0]
N/A% of 400.3 MiB | | Elapsed Time: 0:00:00 ETA: --:--:--
0% of 400.3 MiB | | Elapsed Time: 0:00:00 ETA: 0:15:31
0% of 400.3 MiB | | Elapsed Time: 0:00:00 ETA: 0:10:43
0% of 400.3 MiB | | Elapsed Time: 0:00:00 ETA: 0:07:57
0% of 400.3 MiB | | Elapsed Time: 0:00:00 ETA: 0:06:12
0% of 400.3 MiB | | Elapsed Time: 0:00:00 ETA: 0:05:55
0% of 400.3 MiB | | Elapsed Time: 0:00:00 ETA: 0:05:16
0% of 400.3 MiB | | Elapsed Time: 0:00:01 ETA: 0:04:50
0% of 400.3 MiB | | Elapsed Time: 0:00:01 ETA: 0:04:32
0% of 400.3 MiB | | Elapsed Time: 0:00:01 ETA: 0:04:34
0% of 400.3 MiB | | Elapsed Time: 0:00:01 ETA: 0:04:08
0% of 400.3 MiB | | Elapsed Time: 0:00:01 ETA: 0:04:01
0% of 400.3 MiB | | Elapsed Time: 0:00:01 ETA: 0:03:45
0% of 400.3 MiB | | Elapsed Time: 0:00:01 ETA: 0:03:32
0% of 400.3 MiB | | Elapsed Time: 0:00:01 ETA: 0:03:22
1% of 400.3 MiB | | Elapsed Time: 0:00:02 ETA: 0:03:20
1% of 400.3 MiB | | Elapsed Time: 0:00:02 ETA: 0:03:13
1% of 400.3 MiB | | Elapsed Time: 0:00:02 ETA: 0:02:43
1% of 400.3 MiB | | Elapsed Time: 0:00:02 ETA: 0:02:31
1% of 400.3 MiB | | Elapsed Time: 0:00:02 ETA: 0:02:25
1% of 400.3 MiB | | Elapsed Time: 0:00:02 ETA: 0:02:17
1% of 400.3 MiB | | Elapsed Time: 0:00:02 ETA: 0:02:12
1% of 400.3 MiB | | Elapsed Time: 0:00:02 ETA: 0:01:59
2% of 400.3 MiB | | Elapsed Time: 0:00:03 ETA: 0:01:51
2% of 400.3 MiB | | Elapsed Time: 0:00:03 ETA: 0:01:46
2% of 400.3 MiB | | Elapsed Time: 0:00:03 ETA: 0:01:44
2% of 400.3 MiB | | Elapsed Time: 0:00:03 ETA: 0:01:34
2% of 400.3 MiB | | Elapsed Time: 0:00:03 ETA: 0:01:28
3% of 400.3 MiB | | Elapsed Time: 0:00:03 ETA: 0:01:24
3% of 400.3 MiB | | Elapsed Time: 0:00:03 ETA: 0:01:18
3% of 400.3 MiB | | Elapsed Time: 0:00:03 ETA: 0:01:15
3% of 400.3 MiB | | Elapsed Time: 0:00:04 ETA: 0:01:11
3% of 400.3 MiB | | Elapsed Time: 0:00:04 ETA: 0:01:08
4% of 400.3 MiB | | Elapsed Time: 0:00:04 ETA: 0:01:01
4% of 400.3 MiB | | Elapsed Time: 0:00:04 ETA: 0:00:58
4% of 400.3 MiB |# | Elapsed Time: 0:00:04 ETA: 0:00:55
5% of 400.3 MiB |# | Elapsed Time: 0:00:04 ETA: 0:00:53
5% of 400.3 MiB |# | Elapsed Time: 0:00:04 ETA: 0:00:50
5% of 400.3 MiB |# | Elapsed Time: 0:00:04 ETA: 0:00:48
6% of 400.3 MiB |# | Elapsed Time: 0:00:04 ETA: 0:00:44
6% of 400.3 MiB |# | Elapsed Time: 0:00:04 ETA: 0:00:42
6% of 400.3 MiB |# | Elapsed Time: 0:00:05 ETA: 0:00:40
7% of 400.3 MiB |# | Elapsed Time: 0:00:05 ETA: 0:00:38
7% of 400.3 MiB |# | Elapsed Time: 0:00:05 ETA: 0:00:37
7% of 400.3 MiB |# | Elapsed Time: 0:00:05 ETA: 0:00:34
8% of 400.3 MiB |# | Elapsed Time: 0:00:05 ETA: 0:00:32
8% of 400.3 MiB |# | Elapsed Time: 0:00:05 ETA: 0:00:31
9% of 400.3 MiB |## | Elapsed Time: 0:00:05 ETA: 0:00:29
9% of 400.3 MiB |## | Elapsed Time: 0:00:05 ETA: 0:00:28
10% of 400.3 MiB |## | Elapsed Time: 0:00:05 ETA: 0:00:26
11% of 400.3 MiB |## | Elapsed Time: 0:00:05 ETA: 0:00:24
11% of 400.3 MiB |## | Elapsed Time: 0:00:06 ETA: 0:00:24
12% of 400.3 MiB |## | Elapsed Time: 0:00:06 ETA: 0:00:22
12% of 400.3 MiB |## | Elapsed Time: 0:00:06 ETA: 0:00:21
13% of 400.3 MiB |## | Elapsed Time: 0:00:06 ETA: 0:00:20
13% of 400.3 MiB |### | Elapsed Time: 0:00:06 ETA: 0:00:20
14% of 400.3 MiB |### | Elapsed Time: 0:00:06 ETA: 0:00:18
15% of 400.3 MiB |### | Elapsed Time: 0:00:06 ETA: 0:00:17
16% of 400.3 MiB |### | Elapsed Time: 0:00:06 ETA: 0:00:16
16% of 400.3 MiB |### | Elapsed Time: 0:00:06 ETA: 0:00:16
17% of 400.3 MiB |### | Elapsed Time: 0:00:06 ETA: 0:00:14
18% of 400.3 MiB |#### | Elapsed Time: 0:00:07 ETA: 0:00:14
19% of 400.3 MiB |#### | Elapsed Time: 0:00:07 ETA: 0:00:13
19% of 400.3 MiB |#### | Elapsed Time: 0:00:07 ETA: 0:00:13
20% of 400.3 MiB |#### | Elapsed Time: 0:00:07 ETA: 0:00:12
21% of 400.3 MiB |#### | Elapsed Time: 0:00:07 ETA: 0:00:12
22% of 400.3 MiB |#### | Elapsed Time: 0:00:07 ETA: 0:00:11
22% of 400.3 MiB |#### | Elapsed Time: 0:00:07 ETA: 0:00:11
23% of 400.3 MiB |##### | Elapsed Time: 0:00:07 ETA: 0:00:11
24% of 400.3 MiB |##### | Elapsed Time: 0:00:07 ETA: 0:00:11
24% of 400.3 MiB |##### | Elapsed Time: 0:00:08 ETA: 0:00:10
25% of 400.3 MiB |##### | Elapsed Time: 0:00:08 ETA: 0:00:10
26% of 400.3 MiB |##### | Elapsed Time: 0:00:08 ETA: 0:00:10
27% of 400.3 MiB |##### | Elapsed Time: 0:00:08 ETA: 0:00:10
27% of 400.3 MiB |###### | Elapsed Time: 0:00:08 ETA: 0:00:10
28% of 400.3 MiB |###### | Elapsed Time: 0:00:08 ETA: 0:00:10
29% of 400.3 MiB |###### | Elapsed Time: 0:00:08 ETA: 0:00:09
30% of 400.3 MiB |###### | Elapsed Time: 0:00:08 ETA: 0:00:09
30% of 400.3 MiB |###### | Elapsed Time: 0:00:08 ETA: 0:00:09
31% of 400.3 MiB |###### | Elapsed Time: 0:00:08 ETA: 0:00:09
32% of 400.3 MiB |####### | Elapsed Time: 0:00:09 ETA: 0:00:09
32% of 400.3 MiB |####### | Elapsed Time: 0:00:09 ETA: 0:00:09
33% of 400.3 MiB |####### | Elapsed Time: 0:00:09 ETA: 0:00:09
34% of 400.3 MiB |####### | Elapsed Time: 0:00:09 ETA: 0:00:09
35% of 400.3 MiB |####### | Elapsed Time: 0:00:09 ETA: 0:00:09
35% of 400.3 MiB |####### | Elapsed Time: 0:00:09 ETA: 0:00:08
36% of 400.3 MiB |######## | Elapsed Time: 0:00:09 ETA: 0:00:08
37% of 400.3 MiB |######## | Elapsed Time: 0:00:09 ETA: 0:00:08
38% of 400.3 MiB |######## | Elapsed Time: 0:00:09 ETA: 0:00:08
38% of 400.3 MiB |######## | Elapsed Time: 0:00:09 ETA: 0:00:08
39% of 400.3 MiB |######## | Elapsed Time: 0:00:10 ETA: 0:00:08
40% of 400.3 MiB |######## | Elapsed Time: 0:00:10 ETA: 0:00:08
40% of 400.3 MiB |######### | Elapsed Time: 0:00:10 ETA: 0:00:08
41% of 400.3 MiB |######### | Elapsed Time: 0:00:10 ETA: 0:00:08
42% of 400.3 MiB |######### | Elapsed Time: 0:00:10 ETA: 0:00:08
43% of 400.3 MiB |######### | Elapsed Time: 0:00:10 ETA: 0:00:07
43% of 400.3 MiB |######### | Elapsed Time: 0:00:10 ETA: 0:00:07
44% of 400.3 MiB |######### | Elapsed Time: 0:00:10 ETA: 0:00:07
45% of 400.3 MiB |######### | Elapsed Time: 0:00:10 ETA: 0:00:07
46% of 400.3 MiB |########## | Elapsed Time: 0:00:10 ETA: 0:00:07
46% of 400.3 MiB |########## | Elapsed Time: 0:00:11 ETA: 0:00:07
47% of 400.3 MiB |########## | Elapsed Time: 0:00:11 ETA: 0:00:07
48% of 400.3 MiB |########## | Elapsed Time: 0:00:11 ETA: 0:00:07
49% of 400.3 MiB |########## | Elapsed Time: 0:00:11 ETA: 0:00:07
49% of 400.3 MiB |########## | Elapsed Time: 0:00:11 ETA: 0:00:06
50% of 400.3 MiB |########### | Elapsed Time: 0:00:11 ETA: 0:00:06
51% of 400.3 MiB |########### | Elapsed Time: 0:00:11 ETA: 0:00:06
52% of 400.3 MiB |########### | Elapsed Time: 0:00:11 ETA: 0:00:06
52% of 400.3 MiB |########### | Elapsed Time: 0:00:11 ETA: 0:00:06
53% of 400.3 MiB |########### | Elapsed Time: 0:00:11 ETA: 0:00:06
54% of 400.3 MiB |########### | Elapsed Time: 0:00:12 ETA: 0:00:06
54% of 400.3 MiB |############ | Elapsed Time: 0:00:12 ETA: 0:00:06
55% of 400.3 MiB |############ | Elapsed Time: 0:00:12 ETA: 0:00:06
56% of 400.3 MiB |############ | Elapsed Time: 0:00:12 ETA: 0:00:06
57% of 400.3 MiB |############ | Elapsed Time: 0:00:12 ETA: 0:00:05
57% of 400.3 MiB |############ | Elapsed Time: 0:00:12 ETA: 0:00:05
58% of 400.3 MiB |############ | Elapsed Time: 0:00:12 ETA: 0:00:05
59% of 400.3 MiB |############# | Elapsed Time: 0:00:12 ETA: 0:00:05
60% of 400.3 MiB |############# | Elapsed Time: 0:00:12 ETA: 0:00:05
60% of 400.3 MiB |############# | Elapsed Time: 0:00:13 ETA: 0:00:05
61% of 400.3 MiB |############# | Elapsed Time: 0:00:13 ETA: 0:00:05
62% of 400.3 MiB |############# | Elapsed Time: 0:00:13 ETA: 0:00:05
63% of 400.3 MiB |############# | Elapsed Time: 0:00:13 ETA: 0:00:05
63% of 400.3 MiB |############## | Elapsed Time: 0:00:13 ETA: 0:00:05
64% of 400.3 MiB |############## | Elapsed Time: 0:00:13 ETA: 0:00:04
65% of 400.3 MiB |############## | Elapsed Time: 0:00:13 ETA: 0:00:04
66% of 400.3 MiB |############## | Elapsed Time: 0:00:13 ETA: 0:00:04
66% of 400.3 MiB |############## | Elapsed Time: 0:00:13 ETA: 0:00:04
67% of 400.3 MiB |############## | Elapsed Time: 0:00:13 ETA: 0:00:04
68% of 400.3 MiB |############### | Elapsed Time: 0:00:14 ETA: 0:00:04
68% of 400.3 MiB |############### | Elapsed Time: 0:00:14 ETA: 0:00:04
69% of 400.3 MiB |############### | Elapsed Time: 0:00:14 ETA: 0:00:04
70% of 400.3 MiB |############### | Elapsed Time: 0:00:14 ETA: 0:00:04
71% of 400.3 MiB |############### | Elapsed Time: 0:00:14 ETA: 0:00:04
71% of 400.3 MiB |############### | Elapsed Time: 0:00:14 ETA: 0:00:03
72% of 400.3 MiB |############### | Elapsed Time: 0:00:14 ETA: 0:00:03
73% of 400.3 MiB |################ | Elapsed Time: 0:00:14 ETA: 0:00:03
74% of 400.3 MiB |################ | Elapsed Time: 0:00:14 ETA: 0:00:03
74% of 400.3 MiB |################ | Elapsed Time: 0:00:14 ETA: 0:00:03
75% of 400.3 MiB |################ | Elapsed Time: 0:00:15 ETA: 0:00:03
76% of 400.3 MiB |################ | Elapsed Time: 0:00:15 ETA: 0:00:03
77% of 400.3 MiB |################ | Elapsed Time: 0:00:15 ETA: 0:00:03
77% of 400.3 MiB |################# | Elapsed Time: 0:00:15 ETA: 0:00:03
78% of 400.3 MiB |################# | Elapsed Time: 0:00:15 ETA: 0:00:02
79% of 400.3 MiB |################# | Elapsed Time: 0:00:15 ETA: 0:00:02
79% of 400.3 MiB |################# | Elapsed Time: 0:00:15 ETA: 0:00:02
80% of 400.3 MiB |################# | Elapsed Time: 0:00:15 ETA: 0:00:02
81% of 400.3 MiB |################# | Elapsed Time: 0:00:15 ETA: 0:00:02
82% of 400.3 MiB |################## | Elapsed Time: 0:00:15 ETA: 0:00:02
82% of 400.3 MiB |################## | Elapsed Time: 0:00:16 ETA: 0:00:02
83% of 400.3 MiB |################## | Elapsed Time: 0:00:16 ETA: 0:00:02
84% of 400.3 MiB |################## | Elapsed Time: 0:00:16 ETA: 0:00:02
85% of 400.3 MiB |################## | Elapsed Time: 0:00:16 ETA: 0:00:02
85% of 400.3 MiB |################## | Elapsed Time: 0:00:16 ETA: 0:00:01
86% of 400.3 MiB |################### | Elapsed Time: 0:00:16 ETA: 0:00:01
87% of 400.3 MiB |################### | Elapsed Time: 0:00:16 ETA: 0:00:01
88% of 400.3 MiB |################### | Elapsed Time: 0:00:16 ETA: 0:00:01
88% of 400.3 MiB |################### | Elapsed Time: 0:00:16 ETA: 0:00:01
89% of 400.3 MiB |################### | Elapsed Time: 0:00:17 ETA: 0:00:01
90% of 400.3 MiB |################### | Elapsed Time: 0:00:17 ETA: 0:00:01
90% of 400.3 MiB |#################### | Elapsed Time: 0:00:17 ETA: 0:00:01
91% of 400.3 MiB |#################### | Elapsed Time: 0:00:17 ETA: 0:00:01
92% of 400.3 MiB |#################### | Elapsed Time: 0:00:17 ETA: 0:00:01
93% of 400.3 MiB |#################### | Elapsed Time: 0:00:17 ETA: 0:00:00
93% of 400.3 MiB |#################### | Elapsed Time: 0:00:17 ETA: 0:00:00
94% of 400.3 MiB |#################### | Elapsed Time: 0:00:17 ETA: 0:00:00
95% of 400.3 MiB |#################### | Elapsed Time: 0:00:17 ETA: 0:00:00
96% of 400.3 MiB |##################### | Elapsed Time: 0:00:17 ETA: 0:00:00
96% of 400.3 MiB |##################### | Elapsed Time: 0:00:18 ETA: 0:00:00
97% of 400.3 MiB |##################### | Elapsed Time: 0:00:18 ETA: 0:00:00
98% of 400.3 MiB |##################### | Elapsed Time: 0:00:18 ETA: 0:00:00
99% of 400.3 MiB |##################### | Elapsed Time: 0:00:18 ETA: 0:00:00
99% of 400.3 MiB |##################### | Elapsed Time: 0:00:18 ETA: 0:00:00
100% of 400.3 MiB |######################| Elapsed Time: 0:00:19 Time: 0:00:19
Then create a GeoViews Object with a GeoViews Element Shape, display it and put a gv.tile_sources in the background.
# hv.help(gv.Shape)
(gv.Shape(hintereisferner).opts(fill_color=None) *
gts.tile_sources['EsriImagery']).opts(width=800, height=500)
The GeoViews Object and Element is similar to HoloViews Objects and Elements for geographical data.
print(gv.Shape(hintereisferner))
:Shape [Longitude,Latitude]
And so similar a visualisation is stored for each GeoView Element, which can be used like an HoloView Object. So as a last example you also can plot all European glaciers in one interactive plot by using an Polygons Element of GeoViews:
(gv.Polygons(europe_glacier)*
gts.tile_sources['StamenTerrain']).opts(width=800, height=500)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
/usr/local/pyenv/versions/3.8.10/lib/python3.8/site-packages/IPython/core/formatters.py in __call__(self, obj, include, exclude)
968
969 if method is not None:
--> 970 return method(include=include, exclude=exclude)
971 return None
972 else:
/usr/local/pyenv/versions/3.8.10/lib/python3.8/site-packages/holoviews/core/dimension.py in _repr_mimebundle_(self, include, exclude)
1315 combined and returned.
1316 """
-> 1317 return Store.render(self)
1318
1319
/usr/local/pyenv/versions/3.8.10/lib/python3.8/site-packages/holoviews/core/options.py in render(cls, obj)
1403 data, metadata = {}, {}
1404 for hook in hooks:
-> 1405 ret = hook(obj)
1406 if ret is None:
1407 continue
/usr/local/pyenv/versions/3.8.10/lib/python3.8/site-packages/holoviews/ipython/display_hooks.py in pprint_display(obj)
280 if not ip.display_formatter.formatters['text/plain'].pprint:
281 return None
--> 282 return display(obj, raw_output=True)
283
284
/usr/local/pyenv/versions/3.8.10/lib/python3.8/site-packages/holoviews/ipython/display_hooks.py in display(obj, raw_output, **kwargs)
250 elif isinstance(obj, (CompositeOverlay, ViewableElement)):
251 with option_state(obj):
--> 252 output = element_display(obj)
253 elif isinstance(obj, (Layout, NdLayout, AdjointLayout)):
254 with option_state(obj):
/usr/local/pyenv/versions/3.8.10/lib/python3.8/site-packages/holoviews/ipython/display_hooks.py in wrapped(element)
144 try:
145 max_frames = OutputSettings.options['max_frames']
--> 146 mimebundle = fn(element, max_frames=max_frames)
147 if mimebundle is None:
148 return {}, {}
/usr/local/pyenv/versions/3.8.10/lib/python3.8/site-packages/holoviews/ipython/display_hooks.py in element_display(element, max_frames)
190 return None
191
--> 192 return render(element)
193
194
/usr/local/pyenv/versions/3.8.10/lib/python3.8/site-packages/holoviews/ipython/display_hooks.py in render(obj, **kwargs)
66 renderer = renderer.instance(fig='png')
67
---> 68 return renderer.components(obj, **kwargs)
69
70
/usr/local/pyenv/versions/3.8.10/lib/python3.8/site-packages/holoviews/plotting/renderer.py in components(self, obj, fmt, comm, **kwargs)
408 doc = Document()
409 with config.set(embed=embed):
--> 410 model = plot.layout._render_model(doc, comm)
411 if embed:
412 return render_model(model, comm)
/usr/local/pyenv/versions/3.8.10/lib/python3.8/site-packages/panel/viewable.py in _render_model(self, doc, comm)
425 if comm is None:
426 comm = state._comm_manager.get_server_comm()
--> 427 model = self.get_root(doc, comm)
428
429 if config.embed:
/usr/local/pyenv/versions/3.8.10/lib/python3.8/site-packages/panel/viewable.py in get_root(self, doc, comm, preprocess)
482 """
483 doc = init_doc(doc)
--> 484 root = self._get_model(doc, comm=comm)
485 if preprocess:
486 self._preprocess(root)
/usr/local/pyenv/versions/3.8.10/lib/python3.8/site-packages/panel/layout/base.py in _get_model(self, doc, root, parent, comm)
111 if root is None:
112 root = model
--> 113 objects = self._get_objects(model, [], doc, root, comm)
114 props = dict(self._init_params(), objects=objects)
115 model.update(**self._process_param_change(props))
/usr/local/pyenv/versions/3.8.10/lib/python3.8/site-packages/panel/layout/base.py in _get_objects(self, model, old_objects, doc, root, comm)
101 else:
102 try:
--> 103 child = pane._get_model(doc, root, model, comm)
104 except RerenderError:
105 return self._get_objects(model, current_objects[:i], doc, root, comm)
/usr/local/pyenv/versions/3.8.10/lib/python3.8/site-packages/panel/pane/holoviews.py in _get_model(self, doc, root, parent, comm)
237 plot = self.object
238 else:
--> 239 plot = self._render(doc, comm, root)
240
241 plot.pane = self
/usr/local/pyenv/versions/3.8.10/lib/python3.8/site-packages/panel/pane/holoviews.py in _render(self, doc, comm, root)
302 kwargs['comm'] = comm
303
--> 304 return renderer.get_plot(self.object, **kwargs)
305
306 def _cleanup(self, root):
/usr/local/pyenv/versions/3.8.10/lib/python3.8/site-packages/holoviews/plotting/bokeh/renderer.py in get_plot(self_or_cls, obj, doc, renderer, **kwargs)
71 combining the bokeh model with another plot.
72 """
---> 73 plot = super(BokehRenderer, self_or_cls).get_plot(obj, doc, renderer, **kwargs)
74 if plot.document is None:
75 plot.document = Document() if self_or_cls.notebook_context else curdoc()
/usr/local/pyenv/versions/3.8.10/lib/python3.8/site-packages/holoviews/plotting/renderer.py in get_plot(self_or_cls, obj, doc, renderer, comm, **kwargs)
236 if isinstance(obj, AdjointLayout):
237 obj = Layout(obj)
--> 238 plot = self_or_cls.plotting_class(obj)(obj, renderer=renderer,
239 **plot_opts)
240 defaults = [kd.default for kd in plot.dimensions]
/usr/local/pyenv/versions/3.8.10/lib/python3.8/site-packages/geoviews/plotting/bokeh/plot.py in __init__(self, element, **params)
187
188 def __init__(self, element, **params):
--> 189 super(GeoOverlayPlot, self).__init__(element, **params)
190 self.geographic = any(element.traverse(is_geographic, [_Element]))
191 if self.geographic:
/usr/local/pyenv/versions/3.8.10/lib/python3.8/site-packages/geoviews/plotting/bokeh/plot.py in __init__(self, element, **params)
62
63 def __init__(self, element, **params):
---> 64 super(GeoPlot, self).__init__(element, **params)
65 self.geographic = is_geographic(self.hmap.last)
66 if self.geographic and not isinstance(self.projection, (PlateCarree, Mercator)):
/usr/local/pyenv/versions/3.8.10/lib/python3.8/site-packages/holoviews/plotting/plot.py in __init__(self, overlay, ranges, batched, keys, group_counter, **params)
1576
1577 # Apply data collapse
-> 1578 self.hmap = self._apply_compositor(self.hmap, ranges, self.keys)
1579 self.map_lengths = Counter()
1580 self.group_counter = Counter() if group_counter is None else group_counter
/usr/local/pyenv/versions/3.8.10/lib/python3.8/site-packages/holoviews/plotting/plot.py in _apply_compositor(self, holomap, ranges, keys, dimensions)
1605 for key, slckey in zip(keys, sliced_keys) if slckey in holomap.data.keys()])
1606 else:
-> 1607 mapwise_ranges = self.compute_ranges(holomap, None, None)
1608 frame_ranges = OrderedDict([(key, self.compute_ranges(holomap, key, mapwise_ranges))
1609 for key in holomap.data.keys()])
/usr/local/pyenv/versions/3.8.10/lib/python3.8/site-packages/holoviews/plotting/plot.py in compute_ranges(self, obj, key, ranges)
636 if (not (axiswise and not isinstance(obj, HoloMap)) or
637 (not framewise and isinstance(obj, HoloMap))):
--> 638 self._compute_group_range(group, elements, ranges, framewise,
639 axiswise, robust, self.top_level,
640 prev_frame)
/usr/local/pyenv/versions/3.8.10/lib/python3.8/site-packages/holoviews/plotting/plot.py in _compute_group_range(cls, group, elements, ranges, framewise, axiswise, robust, top_level, prev_frame)
749 data_range = ds.range(el_dim, dimension_range=False)
750 else:
--> 751 data_range = el.range(el_dim, dimension_range=False)
752
753 data_ranges[(el, el_dim)] = data_range
/usr/local/pyenv/versions/3.8.10/lib/python3.8/site-packages/holoviews/core/data/__init__.py in pipelined_fn(*args, **kwargs)
203
204 try:
--> 205 result = method_fn(*args, **kwargs)
206 if PipelineMeta.disable:
207 return result
/usr/local/pyenv/versions/3.8.10/lib/python3.8/site-packages/holoviews/core/data/__init__.py in range(self, dim, data_range, dimension_range)
516 return dim.range
517 elif dim in self.dimensions() and data_range and bool(self):
--> 518 lower, upper = self.interface.range(self, dim)
519 else:
520 lower, upper = (np.NaN, np.NaN)
/usr/local/pyenv/versions/3.8.10/lib/python3.8/site-packages/geoviews/data/geopandas.py in range(cls, dataset, dim)
284 else:
285 vals = dataset.data[dim.name]
--> 286 return vals.min(), vals.max()
287
288 @classmethod
/usr/local/pyenv/versions/3.8.10/lib/python3.8/site-packages/pandas/core/generic.py in min(self, axis, skipna, level, numeric_only, **kwargs)
11211 )
11212 def min(self, axis=None, skipna=None, level=None, numeric_only=None, **kwargs):
> 11213 return NDFrame.min(self, axis, skipna, level, numeric_only, **kwargs)
11214
11215 # pandas\core\generic.py:11009: error: Cannot assign to a method
/usr/local/pyenv/versions/3.8.10/lib/python3.8/site-packages/pandas/core/generic.py in min(self, axis, skipna, level, numeric_only, **kwargs)
10714
10715 def min(self, axis=None, skipna=None, level=None, numeric_only=None, **kwargs):
> 10716 return self._stat_function(
10717 "min", nanops.nanmin, axis, skipna, level, numeric_only, **kwargs
10718 )
/usr/local/pyenv/versions/3.8.10/lib/python3.8/site-packages/pandas/core/generic.py in _stat_function(self, name, func, axis, skipna, level, numeric_only, **kwargs)
10709 if level is not None:
10710 return self._agg_by_level(name, axis=axis, level=level, skipna=skipna)
> 10711 return self._reduce(
10712 func, name=name, axis=axis, skipna=skipna, numeric_only=numeric_only
10713 )
/usr/local/pyenv/versions/3.8.10/lib/python3.8/site-packages/pandas/core/series.py in _reduce(self, op, name, axis, skipna, numeric_only, filter_type, **kwds)
4180 )
4181 with np.errstate(all="ignore"):
-> 4182 return op(delegate, skipna=skipna, **kwds)
4183
4184 def _reindex_indexer(self, new_index, indexer, copy):
/usr/local/pyenv/versions/3.8.10/lib/python3.8/site-packages/pandas/core/nanops.py in f(values, axis, skipna, **kwds)
133 result = alt(values, axis=axis, skipna=skipna, **kwds)
134 else:
--> 135 result = alt(values, axis=axis, skipna=skipna, **kwds)
136
137 return result
/usr/local/pyenv/versions/3.8.10/lib/python3.8/site-packages/pandas/core/nanops.py in new_func(values, axis, skipna, mask, **kwargs)
392 mask = isna(values)
393
--> 394 result = func(values, axis=axis, skipna=skipna, mask=mask, **kwargs)
395
396 if datetimelike:
/usr/local/pyenv/versions/3.8.10/lib/python3.8/site-packages/pandas/core/nanops.py in reduction(values, axis, skipna, mask)
975 result = np.nan
976 else:
--> 977 result = getattr(values, meth)(axis)
978
979 result = _maybe_null_out(result, axis, mask, values.shape)
/usr/local/pyenv/versions/3.8.10/lib/python3.8/site-packages/numpy/core/_methods.py in _amin(a, axis, out, keepdims, initial, where)
41 def _amin(a, axis=None, out=None, keepdims=False,
42 initial=_NoValue, where=True):
---> 43 return umr_minimum(a, axis, None, out, keepdims, initial, where)
44
45 def _sum(a, axis=None, dtype=None, out=None, keepdims=False,
TypeError: '<=' not supported between instances of 'float' and 'str'
:Overlay
.Polygons.I :Polygons [Longitude,Latitude] (RGIId,GLIMSId,BgnDate,EndDate,CenLon,CenLat,O1Region,O2Region,Area,Zmin,Zmax,Zmed,Slope,Aspect,Lmax,Status,Connect,Form,TermType,Surging,Linkages,Name,check_geom)
.WMTS.I :WMTS [Longitude,Latitude]
So this only was a very small look at the capability of HoloViz for data exploration and visualisation. There are much more you can do with HoloViz, but I think it is a package you should have a look at, because with only a few lines of code you can create an interactive plot which allow you to have an quick but also deep look at your data. I really recommend to visit the official HoloViz Tutorial and start using HoloViz :)
What’s next?¶
return to the OGGM documentation
back to the table of contents



